package com.pi.wms.service;

import com.pi.common.CodesConstants;
import com.pi.core.service.UserAccessUtils;
import com.pi.framework.core.util.ConvertUtils;
import com.pi.framework.core.util.SecurityUtils;
import com.pi.framework.core.util.StringUtils;
import com.pi.framework.pro.GenericCrudService;
import com.pi.framework.pro.IGenericRepository;
import com.pi.pro.xcmg.am.common.XcmgAmConstants;
import com.pi.sys.service.UserDivisionService;
import com.pi.wms.common.WmsConstants;
import com.pi.wms.common.WmsTextUtils;
import com.pi.wms.config.WmsClientConfig;
import com.pi.wms.entity.TwaDocAsnDetails;
import com.pi.wms.entity.TwaDocAsnHeader;
import com.pi.wms.entity.TwmBasCustomer;
import com.pi.wms.entity.TwmBasMaterial;
import com.pi.wms.repository.AsnRepository;
import com.pi.wms.repository.CustomerRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.persistence.criteria.*;
import java.io.Serializable;
import java.util.*;




@Slf4j
public abstract class BaseAsnService<T, ID extends Serializable> extends GenericCrudService<T, ID>{

	@Autowired
	protected AsnRepository repository;

	@Autowired
	protected CustomerRepository customerRepository;

	@Autowired
	protected AsnService proxyService;

	@Autowired
	@Qualifier("LOGISTICSSEQSERVICE")
	protected LogisticsSeqService sequenceService;

    @Autowired
    protected UserDivisionService userDivisionService;

    @Autowired
	protected WmsClientConfig wmsClientConfig;

	@Override
	protected Predicate toPredicate(Root<T> root, CriteriaQuery<?> cq, CriteriaBuilder cb, Map<String, ?> query) {
		List<Predicate> list = new ArrayList<Predicate>();
		
		//this.toPredicateTextLike(root, cq, cb, query, "documentNumber", list);
		this.toPredicateSelectEquals(root, cq, cb, query, "type", list);
		this.toPredicateSelectEquals(root, cq, cb, query, "status", list);

		String docno = (String) query.get("no");
		if (!StringUtils.isNullOrBlank(docno)) {
			list.add(cb.or(cb.like(root.get("documentNumber"), "%" + docno + "%"), cb.like(root.get("refDocNumber"), "%" + docno + "%")));
		}
        String category = (String) query.get("category");
        if (!StringUtils.isNullOrBlank(category)) {
            list.add(cb.equal(root.get("category"), category.trim().toUpperCase()));
        }

		String material = (String) query.get("material");
        if (!StringUtils.isNullOrBlank(material)) {
            Join<TwaDocAsnDetails, TwmBasMaterial> materialJoin = root.join("details").join("material");
            list.add(cb.or(cb.like(materialJoin.get("code"), "%" + material.trim() + "%"), cb.like(materialJoin.get("name"), "%" + material.trim() + "%")));
		}

        String suplier = (String) query.get("suplier");
        if (!StringUtils.isNullOrBlank(suplier)) {
            suplier=suplier.trim();
            list.add(cb.or(cb.like(root.get("supplierCode"), "%" + suplier + "%"), cb.like(root.get("supplierName"), "%" + suplier + "%")));
        }

        //配盘单号
        String shipnumber = (String) query.get("deliveryshipnumber");
        if (!StringUtils.isNullOrBlank(shipnumber)) {
            list.add(cb.or(cb.like(root.get("deliveryShipNum"), "%" + shipnumber.trim() + "%")));
        }

        //批次
        String deliveryterms = (String) query.get("deliveryterms");
        if (!StringUtils.isNullOrBlank(deliveryterms)) {
            list.add(cb.and(cb.like(root.get("deliveryTerms"), "%" + deliveryterms.trim() + "%")));
        }

        //产线
        String unloadplace = (String) query.get("planunloadplace");
        if (!StringUtils.isNullOrBlank(unloadplace)) {
            list.add(cb.and(cb.like(root.get("planUnloadPlace"), "%" + unloadplace.trim() + "%")));
        }

        //工位
        String unloaddoor = (String) query.get("planunloaddoor");
        if (!StringUtils.isNullOrBlank(unloaddoor)) {
            list.add(cb.and(cb.like(root.get("planUnloadDoor"), "%" + unloaddoor.trim() + "%")));
        }

        //配盘点
        String deliveryfromplace = (String) query.get("deliveryfromplace");
        if (!StringUtils.isNullOrBlank(deliveryfromplace)) {
            list.add(cb.and(cb.like(root.get("deliveryFromPlace"), "%" + deliveryfromplace.trim() + "%")));
        }

        //容器编号
        String containnumber = (String) query.get("containnumber");
        if (!StringUtils.isNullOrBlank(containnumber)) {
            list.add(cb.and(cb.like(root.get("deliveryContainerNum"), "%" + containnumber.trim() + "%")));
        }

        //状态
        String deliverystatus = (String) query.get("deliverystatus");
        if (!StringUtils.isNullOrBlank(deliverystatus)) {
            if ("0000".equalsIgnoreCase(deliverystatus)){
                list.add(cb.or(cb.equal(root.get("deliveryLastStatus"), "0000"), cb.equal(root.get("deliveryLastStatus"), "0150")));
            }
            if ("0150".equalsIgnoreCase(deliverystatus)){
                list.add(cb.or(cb.equal(root.get("deliveryLastStatus"), "0000"), cb.equal(root.get("deliveryLastStatus"), "0150")));
            }
            if ("0210".equalsIgnoreCase(deliverystatus)){
                list.add(cb.equal(root.get("deliveryLastStatus"), deliverystatus.trim().toUpperCase()));
            }
            if ("0880".equalsIgnoreCase(deliverystatus)){
                list.add(cb.equal(root.get("deliveryLastStatus"), deliverystatus.trim().toUpperCase()));
            }
            if ("0850".equalsIgnoreCase(deliverystatus)){
                list.add(cb.equal(root.get("deliveryLastStatus"), deliverystatus.trim().toUpperCase()));
            }
        }

        //
        Date date=null;
        String fromdate = (String) query.get("fromdate");
        if (!StringUtils.isNullOrBlank(fromdate)) {
            date = WmsTextUtils.plainDate(fromdate,true);
            if (date!=null){
                list.add(cb.greaterThanOrEqualTo(root.get("createdDate"), date));
            }
        }
        String todate = (String) query.get("todate");
        if (!StringUtils.isNullOrBlank(todate)) {
            date = WmsTextUtils.plainDate(todate,false);
            if (date!=null){
                list.add(cb.lessThanOrEqualTo(root.get("createdDate"), date));
            }
        }

        //
        String[] incltypes = ConvertUtils.convertToStringArray(query.get("includeTypes"));
        List<String> indoctypes=null;
        if (incltypes != null) {
            indoctypes = Arrays.asList(incltypes);
            if (indoctypes != null && indoctypes.size() > 0) {
                Predicate p = root.get("type").in(indoctypes);
                list.add(cb.and(p));
            }
        }
        String[] excltypes = ConvertUtils.convertToStringArray(query.get("excludeTypes"));
        List<String> exdoctypes=null;
        if (excltypes != null) {
            exdoctypes = Arrays.asList(excltypes);
            if (exdoctypes != null && exdoctypes.size() > 0) {
                Predicate p = root.get("type").in(exdoctypes);
                list.add(cb.and(cb.not(p)));
            }
        }

        //页面选择
        Long divisionid= UserAccessUtils.getCurrentDivision();
        if ((divisionid!=null) && (divisionid>0L)){
            list.add(cb.equal(root.get("divisionId"), divisionid));
        }
        //权限控制
        List<Long> userDivisionIds = this.userDivisionService.findIdsByUsersId(SecurityUtils.getLoginUserId());
        if ((userDivisionIds!=null)&&(userDivisionIds.size()>0)){
            Predicate p = root.get("divisionId").in(userDivisionIds);
            list.add(cb.and(p));
        }

		//默认条件
		//list.add(cb.lessThan(root.get("status"), WmsConstants.ASN_STATUS_CANCELL));
        String option=CodesConstants.COMMON_FLAG_NO;
		if (query.get(WmsConstants.DOCUMENT_QUERY_OPTION)!=null){
            option=(String)query.get(WmsConstants.DOCUMENT_QUERY_OPTION);
            option=option.trim();
        }
        String status = (String) query.get("status");
        if ( (status!=null) &&
                ((WmsConstants.SO_STATUS_CLOSE.equalsIgnoreCase(status))||(WmsConstants.SO_STATUS_CANCELL.equalsIgnoreCase(status)))){
            option= WmsConstants.DOCUMENT_QUERY_OPTION_SHOWALL;
        }
        if (!option.equalsIgnoreCase(WmsConstants.DOCUMENT_QUERY_OPTION_SHOWALL)){
            list.add(cb.notEqual(root.get("status"), WmsConstants.ASN_STATUS_CLOSE));
            list.add(cb.notEqual(root.get("status"), WmsConstants.ASN_STATUS_CANCELL));
        }
		Predicate[] p = new Predicate[list.size()];
		return cb.and(list.toArray(p));
	}


	protected void extPredicate(List<Predicate> predicates, Root<TwaDocAsnHeader> root, CriteriaQuery<?> cq, CriteriaBuilder builder, Map<String, ?> query){

        //状态
        String deliverystatus = (String) query.get("deliverystatus");
        if (!StringUtils.isNullOrBlank(deliverystatus)) {
            if ("0000".equalsIgnoreCase(deliverystatus)){
                predicates.add(builder.or(builder.equal(root.get("deliveryLastStatus"), "0000"), builder.equal(root.get("deliveryLastStatus"), "0150")));
            }
            if ("0150".equalsIgnoreCase(deliverystatus)){
                predicates.add(builder.or(builder.equal(root.get("deliveryLastStatus"), "0000"), builder.equal(root.get("deliveryLastStatus"), "0150")));
            }
            if ("0210".equalsIgnoreCase(deliverystatus)){
                predicates.add(builder.equal(root.get("deliveryLastStatus"), deliverystatus.trim().toUpperCase()));
            }
            if ("0880".equalsIgnoreCase(deliverystatus)){
                predicates.add(builder.equal(root.get("deliveryLastStatus"), deliverystatus.trim().toUpperCase()));
            }
            if ("0850".equalsIgnoreCase(deliverystatus)){
                predicates.add(builder.equal(root.get("deliveryLastStatus"), deliverystatus.trim().toUpperCase()));
            }
        }

        Date date = null;
        String fromdate = (String)query.get("finfromdate");
        if(!StringUtils.isNullOrBlank(fromdate)) {
            date = WmsTextUtils.plainDate(fromdate, true);
            if(date != null) {
                predicates.add(builder.greaterThanOrEqualTo(root.get("lastModifiedDate"), date));
            }
        }
        String todate = (String)query.get("fintodate");
        if(!StringUtils.isNullOrBlank(todate)) {
            date = WmsTextUtils.plainDate(todate, false);
            if(date != null) {
                predicates.add(builder.lessThanOrEqualTo(root.get("lastModifiedDate"), date));
            }
        }

        //
        date = null;
        fromdate = (String)query.get("bindfromdate");
        if(!StringUtils.isNullOrBlank(fromdate)) {
            date = WmsTextUtils.plainDate(fromdate, true);
            if(date != null) {
                predicates.add(builder.greaterThanOrEqualTo(root.get("createdDate"), date));
            }
        }
        todate = (String)query.get("bindtodate");
        if(!StringUtils.isNullOrBlank(todate)) {
            date = WmsTextUtils.plainDate(todate, false);
            if(date != null) {
                predicates.add(builder.lessThanOrEqualTo(root.get("createdDate"), date));
            }
        }
    }

    public TwaDocAsnHeader findByDocumentNumber(String docNumber) {
        return this.proxyService.findByDocumentNumber(docNumber);
    }

    public String allowOverReceive(TwaDocAsnHeader header){
        return this.proxyService.allowOverReceive(header);
    }

    public String receive(Long docId, String udf01, String udf02, String udf03, String udf04, String udf05, String userCode){
        return this.proxyService.receive(docId, udf01, udf02, udf03, udf04, udf05, userCode);
    }

    public String refreshStatus(Long documentId) {
        return this.proxyService.refreshStatus(documentId);
    }

    public String refreshStatus(TwaDocAsnHeader header, boolean autoClose){
        return this.proxyService.refreshStatus(header, autoClose);
    }

    public String close(Long documentId, String statusCode, String quickMode, String info, String worker){
        return this.proxyService.close(documentId, statusCode, quickMode, info, worker);
    }

    public String close(TwaDocAsnHeader header, String statusCode, String quickMode, String info, String worker){
        return this.proxyService.close(header,statusCode, quickMode, info, worker);
    }

    public String delete(Long documentId, String info, String worker){
        return this.proxyService.delete(documentId, info, worker);
    }
}
